/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.luminia.lightweightstopwatch;

import java.io.IOException;
//import java.text.SimpleDateFormat;
import java.util.ArrayList;

import android.content.Context;
import android.content.SharedPreferences;

/**
* This Class represents the StopWatch.
* 
*/
public class StopWatch {
	
	
	//Settings Variable
	private static final String PREFS_NAME = "StopWatch";
	private SharedPreferences settings;
	private long start_time;
	private long paused_time = 0;
	/*volatile is used to indicate that a variable's 
	 * value will be modified by different threads.
	 */
	private volatile boolean stopped;
	private SharedPreferences.Editor editor;
	private ArrayList<String> laps;
	
	
	public StopWatch(Context context){
		// Restore preferences
        settings = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
        editor = settings.edit();
		stopped = settings.getBoolean("stopped", true);
		start_time = settings.getLong("start_time", 0);
		paused_time = settings.getLong("paused_time", 0);
		setPrefLaps();
	}
	
	/**
	 * TODO  Fix get/set methods for Laps.
	 */
	@SuppressWarnings("unchecked")
	private void setPrefLaps(){
		try {
			laps = (ArrayList<String>) ObjectSerializer.deserialize(settings.getString("laps", ObjectSerializer.serialize(new ArrayList<String>())));
		} 
		catch (IOException e) {
			e.printStackTrace();
	    } 
	}
	
	public int addLap(String lap) {
        assert(null != lap);
        if (laps == null) {
            laps = new ArrayList<String>();
        }
        laps.add(0, lap);
        //save the lap list to preference
        saveState();
        return laps.size();
    }
	
	public int getLapsSize(){
		return laps.size();
	}
	
	public ArrayList<String> getLaps(){
		return laps;
	}
	

	
	private void saveState(){
		editor.putLong("start_time", start_time);
		editor.putLong("paused_time", paused_time);
		editor.putBoolean("stopped", stopped);
		try {
            editor.putString("laps", ObjectSerializer	.serialize(laps));
        } catch (IOException e) {
            e.printStackTrace();
        }
		editor.commit();
	}
	
	public void start() {
		if (paused_time == 0){
			start_time = System.currentTimeMillis();
		}
		else {
			//start_time displacement
			start_time = (System.currentTimeMillis() - (paused_time - start_time));
			paused_time = 0;
		}
		stopped = false;
		saveState();
	}
	
	
	public long stop() {
		stopped = true;
		paused_time = System.currentTimeMillis();
		saveState();
		return getTime();

	}
	
	
	/**
	 * Clear the stopwatch internal state.
	 * 
	 */
	public void clear() {
		paused_time = 0;
		start_time = 0;
		laps.clear();
		saveState();
	}
	
	
	/**
	 * Check the stopwatch internal state
	 * and returns the true if it is stopped
	 * or false if it is running. 
	 * 
	                          
	@return boolean   Returns true if the stopwatch is stopped  
	 *  
	 */
	public boolean isStopped(){
		return stopped;
	}
	
	
	/**
	 * Returns the time of the stopwatch 
	 * in milliseconds, based on it's 
	 * internal state. 
	 * This method is dependent of the system time
	 * so changes on it can affect
	 * the results.
	 * 
	                          
	@return long  The time of the stopwatch in milliseconds 
	 *  
	 */
	public long getTime() {
		if (!stopped){
			return (System.currentTimeMillis() - start_time);
		}
		else {
			/*If it is stopped I follow this simple logic:
			 * time = current_time - start_time - time_paused
			*time paused = current_time - paused_time
			*so joining the 2: time = paused_time - start_time
			*/
			return (paused_time - start_time);
		}
	}
}
